/*
 * Copyright (c) 2010 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.api.data.contacts.v3.model;

import com.google.api.client.util.Key;
import com.google.api.data.gdata.v2.model.Category;
import com.google.api.data.gdata.v2.model.Email;
import com.google.api.data.gdata.v2.model.ExtendedProperty;
import com.google.api.data.gdata.v2.model.Im;
import com.google.api.data.gdata.v2.model.Link;
import com.google.api.data.gdata.v2.model.Name;
import com.google.api.data.gdata.v2.model.Organization;
import com.google.api.data.gdata.v2.model.PhoneNumber;
import com.google.api.data.gdata.v2.model.PostalAddress;
import com.google.api.data.gdata.v2.model.StructuredPostalAddress;
import com.google.api.data.gdata.v2.model.Value;
import com.google.api.data.gdata.v2.model.Where;
import com.google.api.data.gdata.v2.model.batch.BatchEntry;

import java.util.List;

/**
 * Represents a base GData Contacts Entry.
 * 
 * @author Nicolas Garnier
 */
public class Contact extends BatchEntry {

  /** Used to specify that the contact's sensitivity is Confidential. */
  public static final String SENSITIVITY_CONFIDENTIAL = "confidential";

  /** Used to specify that the contact's sensitivity is Normal. */
  public static final String SENSITIVITY_NORMAL = "normal";

  /** Used to specify that the contact's sensitivity is Personal. */
  public static final String SENSITIVITY_PERSONAL = "personal";

  /** Used to specify that the contact's sensitivity is Private. */
  public static final String SENSITIVITY_PRIVATE = "private";

  /** Used to specify that the contact's priority is low. */
  public static final String PRIORITY_LOW = "low";

  /** Used to specify that the contact's priority is normal. */
  public static final String PRIORITY_NORMAL = "normal";

  /** Used to specify that the contact's priority is high. */
  public static final String PRIORITY_HIGH = "high";

  /** Used to specify that the contact is a male. */
  public static final String GENDER_MALE = "male";

  /** Used to specify that the contact is a female. */
  public static final String GENDER_FEMALE = "female";

  /**
   * PlaceHolder to detect the presence of tags.
   */
  public static class IsPresent {
  }

  /** The category for all Contacts */
  public static final Category CATEGORY = new Category();
  static {
    CATEGORY.scheme = "http://schemas.google.com/g/2005#kind";
    CATEGORY.term = "http://schemas.google.com/contact/2008#contact";
  }

  @Key
  public Category category = CATEGORY;

  @Key("gd:name")
  public Name name;

  @Key("content")
  public String notes;

  @Key("gd:deleted")
  private IsPresent deleted;

  public boolean isDeleted() {
    return deleted != null;
  }

  @Key("gd:email")
  public List<Email> emails;

  @Key("gd:im")
  public List<Im> im;

  @Key("gd:postalAddress")
  public List<PostalAddress> postalAddress;

  @Key("gd:structuredPostalAddress")
  public List<StructuredPostalAddress> structuredPostalAddress;

  @Key("gd:organization")
  public List<Organization> organizations;

  @Key("gd:phoneNumber")
  public List<PhoneNumber> phoneNumber;

  /** Additional hidden information */
  @Key("gd:extendedProperty")
  public List<ExtendedProperty> extendedProperties;

  /** Subscriptions to groups */
  @Key("gContact:groupMembershipInfo")
  public List<GroupMembershipInfo> groupMembershipInfo;

  /** A place associated with the contact. */
  @Key("gd:where")
  public Where where;

  /** Contacts billing information. */
  @Key("gContact:billingInformation")
  public String billingInformation;

  /**
   * Contact's birthday date, given in format YYYY-MM-DD (with the year), or
   * --MM-DD (without the year).
   */
  @Key("gContact:birthday@when")
  public String birthday;

  /** Link to a calendar associated with the contact. */
  @Key("gContact:calendarLink")
  public List<CalendarLink> calendarLinks;

  /** Directory server associated with the contact. */
  @Key("gContact:directoryServer")
  public String directoryServer;

  /** Event associated with the contact. */
  @Key("gContact:event")
  public List<Event> events;

  /** External identifier associated with the contact as set by a client */
  @Key("gContact:externalId")
  public ExternalId externalId;

  /**
   * Gender associated with the contact. Valid values are {@link #GENDER_FEMALE}
   * and {@link #GENDER_MALE}.
   */
  @Key("gContact:gender")
  public Value gender;

  /** Hobby associated with the contact. */
  @Key("gContact:hobby")
  public List<String> hobby;

  /** Contact's initials. */
  @Key("gContact:initials")
  public String initials;

  /** Jot associated with the contact. */
  @Key("gContact:jot")
  public List<Jot> jots;

  /** Language associated with the contact. */
  @Key("gContact:language")
  public List<Language> language;

  /** Maiden name associated with the contact. */
  @Key("gContact:maidenName")
  public String maidenName;

  /**
   * Specifies the mileage for the entity represented by the contact. Can be
   * used for example to document distance needed for reimbursement purposes.
   * The value is not interpreted.
   */
  @Key("gContact:mileage")
  public String mileage;

  /**
   * Specifies the nickname of the person represented by the contact. The
   * element cannot be repeated.
   */
  @Key("gContact:nickname")
  public String nickname;

  /**
   * Specifies the occupation/profession of the person specified by the contact.
   */
  @Key("gContact:occupation")
  public String occupation;

  /**
   * Specifies contact's priority. Can be either low, normal or high. Valid
   * values are {@link #PRIORITY_HIGH}, {@link #PRIORITY_LOW} and
   * {@link #PRIORITY_NORMAL}.
   */
  @Key("gContact:priority@rel")
  public String priority;

  /**
   * This element describe another entity (usually a person) that is in a
   * relation of some kind with the contact.
   */
  @Key("gContact:relation")
  public List<Relation> relation;

  /**
   * Specifies contact's sensitivity. Valid values are
   * {@link #SENSITIVITY_CONFIDENTIAL}, {@link #SENSITIVITY_NORMAL},
   * {@link #SENSITIVITY_PERSONAL} and {@link #SENSITIVITY_PRIVATE}.
   */
  @Key("gContact:sensitivity@rel")
  public String sensitivity;

  /** Specifies short name of the person represented by the contact. */
  @Key("gContact:shortName")
  public String shortName;

  /** Specifies the subject of the contact. */
  @Key("gContact:subject")
  public String subject;

  /** Represents an arbitrary key-value pair attached to the contact. */
  @Key("gContact:userDefinedField")
  public List<UserDefinedField> userDefinedFields;

  /** Describes websites associated with the contact, including links. */
  @Key("gContact:website")
  public List<Website> websites;

  /**
   * Returns the link to the photo of the Contact. The etag of the link is null
   * if there is no existing photo.
   * 
   * @return The link to the photo of the Contact.
   */
  public String getPhotoLink() {
    return Link.find(links, "http://schemas.google.com/contacts/2008/rel#photo");
  }
}
